package cg.server;

import cg.common.UserAction;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Sokethoste
 * @author Tim Beer
 */
public class Player implements Runnable {

    private List _listeners = new ArrayList();
    Socket _s;
    ObjectInputStream _input;
    ObjectOutputStream _output;
    Thread _receiver;
    String _playerName;

    public String getPlayerName() {
        return _playerName;
    }

    public synchronized void addEventListener(PlayerEventListener listener) {
        _listeners.add(listener);
    }

    public synchronized void removeEventListener(PlayerEventListener listener) {
        _listeners.remove(listener);
    }

    //Konstruktor
    public Player(Socket s) {
        _s = s;
    }

    //Diese Methode wird von ServerMain aufgerufen, wenn der Server den Client akzeptiert hat
    //Dem Spieler wird der Socket _s übergeben
    //init() holt sich von _s die OIS und OOS
    //Vom receiver wird ein neuer Thread erstellt
    public void Init() throws IOException {
        _input = new ObjectInputStream(_s.getInputStream());
        _output = new ObjectOutputStream(_s.getOutputStream());
        _receiver = new Thread(this);
        _receiver.start();

        int i = 0;
        while (_playerName == null || i++ > 10) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private synchronized void firePlayerEvent(Object obj) {
        PlayerEvent event = new PlayerEvent(this, obj);
        Iterator i = _listeners.iterator();

        while (i.hasNext()) {
            ((PlayerEventListener) i.next()).handlePlayerEvent(event);
        }
    }

    //Methode zum senden von Objekten. es wird der ObjectOutputStream der Clients genutzt
    public void SendObject(Object obj) throws IOException {
        _output.writeObject(obj);
    }

    @Override
    public void run() {
        //Der Client hört den ObjectInputStream ständig ab und waret auf Objekte
        //wenn der Client ein Objekt erhält, prüft er ob es ein String-Objekt oder ein firePlayerEvent ist
        //String-Objekt wird genutzt um Spielername zu übertragen
        //firePlayerEvent wird genutzt um Spielinteraktionen zu übertragen
        while (true) {
            try {
                Object readObject = _input.readObject();
                if (readObject.getClass().equals(String.class)) {
                    _playerName = (String) readObject;
                } else {
                    firePlayerEvent(readObject);
                }

                System.out.print("Got a message: " + readObject.toString());

            } catch (IOException ex) {
                Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
                break;
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }
}
